package com.medical.data.component;


import com.fasterxml.jackson.core.JsonParseException;
import com.medical.data.exception.MyException;
import com.medical.data.exception.MyUploadException;
import com.medical.data.utils.Result;
import io.jsonwebtoken.SignatureException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.UnexpectedTypeException;
import javax.websocket.DecodeException;
import java.nio.file.AccessDeniedException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
//这个类就是处理异常类的
@RestControllerAdvice
public class GlobalExceptionComponent {
    @ExceptionHandler(Exception.class)
    public Result error(Exception e){
        e.printStackTrace();
        return Result.error();
    }
    @ExceptionHandler(MyException.class)
    public Result error(MyException e){
        return Result.error().code(e.getCode()).message(e.getMessage());
    }

    @ExceptionHandler(MyUploadException.class)
    public Result error(MyUploadException e){
        return Result.error().code(e.getCode()).message(e.getMessage()).errno(e.getErrno());
    }

    /**
     * MethodArgumentNotValidException.class,ConstraintViolationException.class,BindException.class
     * 这三个异常类是处理validator信息的
     * @param e
     * @return
     */
    @ExceptionHandler(value = {MethodArgumentNotValidException.class})
    public Result error(MethodArgumentNotValidException e){
        //刨析使用lambda对list操作
        //e.getBindingResult().getAllErrors().stream()获取一个list列表
        //map(ObjectError::getDefaultMessage)取出列表中某一个字段的所有值，返回的还是流文件，有点类似list
        //collect可以继续对返回的流进行操作
        //Collectors.toList() 对流里面的每个数据进行转化成一个列表
        List<String> collect = e.getBindingResult().getAllErrors().stream().map(ObjectError::getDefaultMessage)
                .collect(Collectors.toList());
        return Result.error().data("error",collect).message(collect.toString());
    }
    @ExceptionHandler(value = {BindException.class})
    public Result error(BindException e){
        return Result.error().message(e.getBindingResult().getAllErrors().stream().map(ObjectError::getDefaultMessage).collect(Collectors.joining(",")));
    }
    @ExceptionHandler(ConstraintViolationException.class)
    public Result error(ConstraintViolationException e){
        return Result.error().message(e.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.joining(",")));

    }
    @ExceptionHandler(value = HttpMessageNotReadableException.class)
    public Result error(HttpMessageNotReadableException e){
        log.info("=======>{}",e.getMessage() );
        return Result.error().message("请检查参数是否传递了");
    }
    @ExceptionHandler(value = HttpMessageNotWritableException.class)
    public Result error(HttpMessageNotWritableException e){
//        return R.error().message(e.getHttpInputMessage().getBody().mark(1))
        return Result.error().message(e.getMessage());
    }
    @ExceptionHandler(value = AccessDeniedException.class)
    public Result error(AccessDeniedException e){
        List<String> list = new ArrayList<>();
        list.add(e.getLocalizedMessage());
        list.add(e.getReason());
        list.add(e.getMessage());
        list.add(e.getFile());
        list.add(e.getOtherFile());
        list.add(e.getCause().getMessage());
        return Result.error().message(list.toString());
    }
    @ExceptionHandler(value = MissingServletRequestParameterException.class)
    public Result error(MissingServletRequestParameterException e){
        return Result.error().data("error","需要传递参数:"+e.getParameterName()+",参数类型:"+e.getParameterType())
                .message("需要传递参数:"+e.getParameterName()+",参数类型:"+e.getParameterType());
    }
    @ExceptionHandler(value =HttpRequestMethodNotSupportedException.class)
    public Result error(HttpRequestMethodNotSupportedException e) {
        return Result.error().message( "该接口不支持:" + e.getMethod() + "类型,请正确的传递");
    }
//    @ExceptionHandler(value = BadSqlGrammarException.class)
//    public Result error(BadSqlGrammarException e) {
//        return Result.error().message( "错误信息:"+e.getSQLException().getSQLState());
//    }

    /**
     * 远程调用参数出错,请检查参数
     * @param e
     * @return
     */
    @ExceptionHandler(value = DecodeException.class)
    public Result error(DecodeException e) {
        return Result.error().message( "错误信息:"+e.getMessage());
    }

    @ExceptionHandler(value = MethodArgumentTypeMismatchException.class)
    public Result error(MethodArgumentTypeMismatchException e) {
        return Result.error().message( "参数传递错误");
    }


    @ExceptionHandler(value = SignatureException.class)
    public Result error(SignatureException e) {
        return Result.error().message( "token错误,请重新登录");
    }


//    @ExceptionHandler(value = SignatureException.class)
//    public R error(MalformedJwtException e) {
//        return R.error().message( "token错误,请重新登录,无法解析");
//    }
//
//
    @ExceptionHandler(value = JsonParseException.class)
    public Result error(JsonParseException e) {
        return Result.error().message("json参数出错，无法转化");
    }

    @ExceptionHandler(value = UnexpectedTypeException.class)
    public Result error(UnexpectedTypeException e){return Result.error().message(e.getMessage());}
}
